/**
 * Copyright (c) 2012 Axa Holding Belgium, SA. All rights reserved.
 * This software is the confidential and proprietary information of the AXA Group.
 */
package chabernac.android.wordbattle.paint.boggle;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.View;
import chabernac.android.wordbattle.R;
import chabernac.android.wordbattle.WordBattleView;
import chabernac.android.wordbattle.WordRasterContext;
import chabernac.android.wordbattle.model.Letter;
import chabernac.android.wordbattle.model.Word;
import chabernac.android.wordbattle.model.iWordRasterListener;
import chabernac.android.wordbattle.paint.iDrawable;


/**
 * image rotation: http://stackoverflow.com/questions/4166917/android-how-to-rotate-a-bitmap-on-a-center-point 
 */

public class BoggleLetterDrawable extends iDrawable {
  private final static Random RANDOM = new Random();
  private final static int ROTATION_ANIMATION_ANGLE = Math.abs(RANDOM.nextInt() %  8);
  private final static int ROTATION_FRAMES = 5;
  private final static int ROTATION_SELECTED = 15;
  
  private final static float RANDOM_LETTER_OFFSET_FRACTION = 0.05F;
  
  private final static int BORDER = 2;
  
  private final Bitmap myOrigBitmap;
  private final Letter myLeter;
  private final Paint myPaint = new Paint();
  
  private Bitmap myBitmap;
  private Bitmap mySelectedLetterBitmap;
  private List<Bitmap> myRotatedBitmaps = new ArrayList<Bitmap>();
  private int myX;
  private int myY;
  
  private int myCurrentFrame = 0;
  private int myDelta = 0;
  private int myRemainingAnimations = 0;
  
  public BoggleLetterDrawable( Letter aLetter ) {
    super();
    
    myOrigBitmap = BitmapFactory.decodeResource( WordRasterContext.getInstance().getContext().getResources(), R.drawable.wooden_block_1 );
    myLeter = aLetter;
    addListener();
    
  }
  
  private void addListener(){
    WordRasterContext.getInstance().getMediator().getWordRaster().addListener( new WordRasterListener() );
  }
  
  private void createBitmap(View aView){
    WordBattleView theWordBattleView = (WordBattleView)aView;
    myX = WordBattleView.BORDER_SIZE + (int)(myLeter.getColumn() * theWordBattleView.getWidthPerColumn());
    myY = WordBattleView.BORDER_SIZE + (int)(myLeter.getRow() * theWordBattleView.getHeightPerRow());
    
    float theMinSize = (float)(Math.min(theWordBattleView.getHeightPerRow(), theWordBattleView.getWidthPerColumn()) * 0.8 );
    myPaint.setTextSize(theMinSize);
    
    myBitmap = Bitmap.createBitmap( (int)theWordBattleView.getWidthPerColumn(), (int)theWordBattleView.getHeightPerRow(), Bitmap.Config.ARGB_8888 );
    Canvas theCanvas = new Canvas(myBitmap);
    myPaint.setAntiAlias( true );
    
    int theWidth = (int)theWordBattleView.getWidthPerColumn() - 2 * BORDER;
    int theHeight = (int)theWordBattleView.getHeightPerRow() - 2 * BORDER;
    
    theCanvas.drawBitmap( myOrigBitmap, null, new Rect( BORDER, BORDER, theWidth, theHeight ), myPaint );
    
    Rect theFontBounds = new Rect();
    myPaint.getTextBounds(myLeter.getLetter(), 0 , 1 , theFontBounds);
    
    float theFontWidth = theFontBounds.width();
    float theFontHeight = theFontBounds.height();
    
    float theXOffset = (theWordBattleView.getWidthPerColumn() - theFontWidth) / 2F;
    float theYOffset = (theWordBattleView.getHeightPerRow() - theFontHeight) / 2F;
    
    float theX = theXOffset + RANDOM.nextInt() % (theWordBattleView.getWidthPerColumn() * RANDOM_LETTER_OFFSET_FRACTION);
    float theY = theYOffset + theFontHeight + RANDOM.nextInt() % (theWordBattleView.getHeightPerRow() * RANDOM_LETTER_OFFSET_FRACTION);
    
    myPaint.setColor(Color.BLACK);
    myPaint.setAlpha( 200 );
    myPaint.setFakeBoldText( true );
    myPaint.setMaskFilter( new BlurMaskFilter( 3, BlurMaskFilter.Blur.NORMAL ) );
    
    theCanvas.drawText(myLeter.getLetter(), theX - theFontBounds.left, theY - theFontBounds.bottom , myPaint);
    
    myPaint.setAlpha( 255 );
    myPaint.setMaskFilter( null );
  }
  
  private Bitmap rotateBitmap(float anAngle, int aBackgroundColor){
    Bitmap theRotatedBitmap = Bitmap.createBitmap(myBitmap.getWidth(), myBitmap.getHeight(), Config.ARGB_8888);
    Canvas canvas = new Canvas(theRotatedBitmap);
    Matrix matrix = new Matrix();
    matrix.setRotate(anAngle,myBitmap.getWidth()/2,myBitmap.getHeight() / 2);
    matrix.mapRect( new RectF(0,0,myBitmap.getWidth(), myBitmap.getHeight()) );
    canvas.concat(matrix);
    if(aBackgroundColor != 0){
      myPaint.setColor(aBackgroundColor);
      canvas.drawRect(BORDER + 2, BORDER + 2, myBitmap.getWidth() - 2 * (BORDER + 2), myBitmap.getHeight() - 2 * (BORDER + 2), myPaint);
      myPaint.setAlpha(220);
    }
    canvas.drawBitmap(myBitmap, 0, 0, myPaint);
    
    return theRotatedBitmap;

  }
  
  private void createRotationAnimationBitmaps(float aStartAngle){
    //create 5 rotations bitmaps
    float theRotationOffset = (float)ROTATION_ANIMATION_ANGLE / (float)ROTATION_FRAMES;
    if(aStartAngle > 0) {
      for(float angle = aStartAngle;angle<aStartAngle + ROTATION_ANIMATION_ANGLE;angle += theRotationOffset){
        myRotatedBitmaps.add(rotateBitmap( angle, 0 ));
      }
    } else {
      for(float angle = aStartAngle;angle>aStartAngle - ROTATION_ANIMATION_ANGLE;angle -= theRotationOffset){
        myRotatedBitmaps.add(rotateBitmap( angle, 0 ));
      }
    }
    
    mySelectedLetterBitmap = rotateBitmap( ROTATION_SELECTED, Color.BLACK );
  }
  
  private Bitmap getCurrentBitmap(){
    if(myRotatedBitmaps.size() == 0) return null;
    Bitmap theBitmap = myRotatedBitmaps.get( myCurrentFrame );
    myCurrentFrame += myDelta;
    
    if(myCurrentFrame >= ROTATION_FRAMES - 1) myDelta *= -1;
    if(myCurrentFrame <= 0) myDelta *=-1;
    
    myRemainingAnimations--;
    if(myRemainingAnimations <= 0){
      myDelta = 0;
      myCurrentFrame = 0;
    }
    return theBitmap;
  }
  
  private void startAnimation(WordBattleView aView){
    myDelta = 1;
    myRemainingAnimations = 20;
    
//    aView.requestAnimation();
  }

  @Override
  public synchronized void paint( Canvas aCanvas, View aView ) {
    if(myBitmap == null){
      createBitmap(aView);
      
      float theRotation = (float)(RANDOM.nextInt() % 5); //* Math.PI / 180);
      createRotationAnimationBitmaps( theRotation );
    }
    
    if(WordRasterContext.getInstance().getMediator().getWordRaster().getSelectedLetters().contains(  myLeter )){
      myPaint.setAlpha( 220 );
      aCanvas.drawBitmap( mySelectedLetterBitmap, myX, myY, myPaint );
    } else {
      myPaint.setAlpha( 255 );
      aCanvas.drawBitmap( getCurrentBitmap(), myX, myY, myPaint );
    }
    
  }
  
  public class WordRasterListener implements iWordRasterListener {

    @Override
    public void selectionChanged(List<Letter> aSelectedLetters) {
    }

    @Override
    public void wordFound( Word aWord ) {
      if(aWord.getLetters().contains( myLeter )){
//        startAnimation();
      }
    }
  }

}
